/**
 * 基础API服务类
 * 提供统一的HTTP请求方法和错误处理机制
 */

import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
import { message } from 'antd';

/**
 * API响应格式接口
 */
export interface ApiResponse<T = any> {
  /** 响应状态码 */
  code: number;
  /** 响应消息 */
  message: string;
  /** 响应数据 */
  data: T;
  /** 请求是否成功 */
  success: boolean;
  /** 时间戳 */
  timestamp: number;
}

/**
 * 分页响应格式接口
 */
export interface PaginatedResponse<T = any> extends ApiResponse<T> {
  /** 分页信息 */
  pagination: {
    /** 当前页码 */
    current: number;
    /** 每页数量 */
    pageSize: number;
    /** 总数量 */
    total: number;
    /** 总页数 */
    totalPages: number;
  };
}

/**
 * 自定义错误类
 */
export class ApiError extends Error {
  constructor(
    public code: number,
    message: string,
    public details?: any
  ) {
    super(message);
    this.name = 'ApiError';
  }
}

/**
 * 基础服务类
 */
export abstract class BaseService {
  protected axiosInstance: AxiosInstance;

  constructor(baseURL?: string) {
    this.axiosInstance = axios.create({
      baseURL: baseURL || '/api',
      timeout: 15000,
      headers: {
        'Content-Type': 'application/json',
      },
      withCredentials: true,
    });

    // 设置请求拦截器
    this.setupRequestInterceptors();
    
    // 设置响应拦截器
    this.setupResponseInterceptors();
  }

  /**
   * 设置请求拦截器
   */
  private setupRequestInterceptors(): void {
    this.axiosInstance.interceptors.request.use(
      (config) => {
        // 添加认证令牌
        const token = localStorage.getItem('access_token');
        if (token) {
          config.headers.Authorization = `Bearer ${token}`;
        }

        // 添加请求日志
        console.log(`🚀 [API] ${config.method?.toUpperCase()} ${config.url}`, {
          params: config.params,
          data: config.data,
          timestamp: new Date().toISOString(),
        });

        return config;
      },
      (error) => {
        console.error('❌ [API] 请求拦截器错误:', error);
        return Promise.reject(error);
      }
    );
  }

  /**
   * 设置响应拦截器
   */
  private setupResponseInterceptors(): void {
    this.axiosInstance.interceptors.response.use(
      (response: AxiosResponse<ApiResponse>) => {
        console.log(`✅ [API] 请求成功: ${response.config.url}`, {
          status: response.status,
          data: response.data,
          timestamp: new Date().toISOString(),
        });

        // 处理业务响应格式
        const { data } = response;
        
        if (data && typeof data === 'object') {
          // 如果后端返回统一格式
          if ('code' in data && 'success' in data) {
            if (data.success) {
              return response;
            } else {
              // 业务错误
              const error = new ApiError(data.code, data.message || '请求失败');
              this.handleApiError(error);
              return Promise.reject(error);
            }
          }
        }

        return response;
      },
      (error) => {
        console.error('❌ [API] 请求失败:', {
          url: error.config?.url,
          method: error.config?.method,
          status: error.response?.status,
          message: error.message,
          timestamp: new Date().toISOString(),
        });

        this.handleHttpError(error);
        return Promise.reject(error);
      }
    );
  }

  /**
   * 处理HTTP错误
   */
  private handleHttpError(error: any): void {
    if (error.response) {
      // 服务器返回错误状态码
      const { status, data } = error.response;
      
      switch (status) {
        case 400:
          message.error('请求参数错误');
          break;
        case 401:
          message.error('未授权访问，请重新登录');
          localStorage.removeItem('access_token');
          // 跳转到登录页
          window.location.href = '/login';
          break;
        case 403:
          message.error('权限不足，请联系管理员');
          break;
        case 404:
          message.error('请求的资源不存在');
          break;
        case 500:
          message.error('服务器内部错误，请稍后重试');
          break;
        default:
          message.error(`请求失败: ${status}`);
      }
    } else if (error.request) {
      // 请求已发出但没有收到响应
      message.error('网络连接错误，请检查网络设置');
    } else {
      // 请求配置错误
      message.error('请求配置错误');
    }
  }

  /**
   * 处理业务错误
   */
  private handleApiError(error: ApiError): void {
    message.error(error.message || '操作失败');
  }

  /**
   * GET请求
   */
  protected async get<T = any>(url: string, params?: any, config?: AxiosRequestConfig): Promise<T> {
    const response = await this.axiosInstance.get<ApiResponse<T>>(url, {
      params,
      ...config,
    });
    return this.extractData(response);
  }

  /**
   * POST请求
   */
  protected async post<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
    const response = await this.axiosInstance.post<ApiResponse<T>>(url, data, config);
    return this.extractData(response);
  }

  /**
   * PUT请求
   */
  protected async put<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
    const response = await this.axiosInstance.put<ApiResponse<T>>(url, data, config);
    return this.extractData(response);
  }

  /**
   * DELETE请求
   */
  protected async delete<T = any>(url: string, config?: AxiosRequestConfig): Promise<T> {
    const response = await this.axiosInstance.delete<ApiResponse<T>>(url, config);
    return this.extractData(response);
  }

  /**
   * PATCH请求
   */
  protected async patch<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
    const response = await this.axiosInstance.patch<ApiResponse<T>>(url, data, config);
    return this.extractData(response);
  }

  /**
   * 从响应中提取数据
   */
  private extractData<T>(response: AxiosResponse<ApiResponse<T>>): T {
    const { data } = response;
    
    // 如果后端返回统一格式，提取data字段
    if (data && typeof data === 'object' && 'data' in data) {
      return data.data;
    }
    
    // 否则直接返回响应数据
    return data as T;
  }

  /**
   * 上传文件
   */
  protected async upload<T = any>(url: string, formData: FormData, config?: AxiosRequestConfig): Promise<T> {
    const uploadConfig: AxiosRequestConfig = {
      headers: {
        'Content-Type': 'multipart/form-data',
      },
      ...config,
    };
    
    const response = await this.axiosInstance.post<ApiResponse<T>>(url, formData, uploadConfig);
    return this.extractData(response);
  }

  /**
   * 下载文件
   */
  protected async download(url: string, params?: any, filename?: string): Promise<void> {
    const response = await this.axiosInstance.get(url, {
      params,
      responseType: 'blob',
    });

    // 创建下载链接
    const blob = new Blob([response.data]);
    const downloadUrl = window.URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.href = downloadUrl;
    link.download = filename || 'download';
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    window.URL.revokeObjectURL(downloadUrl);
  }
}

export default BaseService;